package com.guchenbo.example.juc;

import com.guchenbo.example.netty4.HelloTask;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.IntStream;

/**
 * @Author guchenbo
 * @Date 2018/10/29.
 */
public class ExecutorDemo {

    public static void main(String[] args) {
        ExecutorDemo demo = new ExecutorDemo();
//        demo.test();

        AtomicBoolean ab = new AtomicBoolean();
        ab.set(false);

        System.out.println(ab.compareAndSet(false, true));
        System.out.println(ab.compareAndSet(true, false));
//        demo.testSimple();
    }

    public void testSimple(){
        HelloTask task = new HelloTask();
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(task);

        System.out.println(task.isHelloThread());

        ExecutorUtils.stop(executor);
    }

    public void test() {
        ExecutorService executor = Executors.newWorkStealingPool();
        HelloTask task = new HelloTask();
        IntStream.range(0, 100).forEach((i) -> {
            executor.submit(task);
        });
        List list = executor.shutdownNow();
        System.out.println(list.size());
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        //        invokeAll(executor);
        //        invokeAllTimeout(executor);

        //        invokeAny(executor);
        invokeAnyTimeout(executor);

        //        System.out.println("invoke any");
        //        String result = null;
        //        try {
        //            result = executor.invokeAny(callables);
        //        } catch (InterruptedException e) {
        //            e.printStackTrace();
        //        } catch (ExecutionException e) {
        //            e.printStackTrace();
        //        }
        //        System.out.println(result);
        executor.shutdown();
    }

    private void invokeAnyTimeout(ExecutorService executor) {
        List<Callable<String>> callables = Arrays
                        .asList(callable("task2", 2), callable("task1", 1), callable("task3", 3));

        System.out.println("invoke any");

        try {
            String result = null;
            try {
                try {
                    result = executor.invokeAny(callables, 5, TimeUnit.SECONDS);
                } catch (TimeoutException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(result);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    private void invokeAny(ExecutorService executor) {
        List<Callable<String>> callables = Arrays
                        .asList(callable("task2", 2), callable("task1", 1), callable("task3", 3));

        System.out.println("invoke any");

        try {
            String result = null;
            try {
                result = executor.invokeAny(callables);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(result);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }

    private void invokeAll(ExecutorService executor) {
        List<Callable<String>> callables = Arrays
                        .asList(callable("task2", 2), callable("task1", 1), callable("task3", 3));

        try {
            System.out.println("invoke all");
            List<Future<String>> fs = executor.invokeAll(callables);
            System.out.println(fs.size());

            //            fs.stream().map(f -> {
            //                try {
            //                    return f.get();
            //                } catch (InterruptedException e) {
            //                    e.printStackTrace();
            //                } catch (ExecutionException e) {
            //                    e.printStackTrace();
            //                }
            //                return "";
            //            }).forEach(s -> System.out.println(s));
            //            executor.invokeAll(callables,5,TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void invokeAllTimeout(ExecutorService executor) {
        List<Callable<String>> callables = Arrays
                        .asList(callable("task2", 2), callable("task1", 1), callable("task3", 3));

        try {
            System.out.println("invoke all");
            List<Future<String>> fs = executor.invokeAll(callables, 2, TimeUnit.SECONDS);
            ;
            System.out.println(fs.size());

            //            fs.stream().map(f -> {
            //                try {
            //                    return f.get();
            //                } catch (InterruptedException e) {
            //                    e.printStackTrace();
            //                } catch (ExecutionException e) {
            //                    e.printStackTrace();
            //                }
            //                return "";
            //            }).forEach(s -> System.out.println(s));
            //
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    Callable<String> callable(String result, long sleepSeconds) {
        return () -> {
            System.out.println(result + " start in " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(sleepSeconds);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(result + " end in " + Thread.currentThread().getName());
            return result;
        };
    }

    class Cl implements Callable<String> {
        private long sleepSeconds;
        private String result;

        public Cl(long sleepSeconds, String result) {
            this.sleepSeconds = sleepSeconds;
            this.result = result;
        }

        @Override
        public String call() throws Exception {
            TimeUnit.SECONDS.sleep(sleepSeconds);
            System.out.println(result + " in " + Thread.currentThread().getName());
            return null;
        }
    }

}
